package com.naiterui.ehp.bs.patient.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.hutool.core.collection.CollUtil;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.bo.cms.FollowUpRecordFormBO;
import com.naiterui.ehp.bp.bo.emr.QaPageBO;
import com.naiterui.ehp.bp.bo.emr.QaRecordBO;
import com.naiterui.ehp.bp.bo.emr.QaRecordDetailBO;
import com.naiterui.ehp.bp.bo.form.DesignFormBO;
import com.naiterui.ehp.bp.bo.form.FormDrawingBO;
import com.naiterui.ehp.bp.bo.form.FormDrawingOptionBO;
import com.naiterui.ehp.bp.constants.QaConstants;
import com.naiterui.ehp.bp.domain.Doctor;
import com.naiterui.ehp.bp.domain.DrFollowUpRecordForm;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.service.IDrFollowUpRecordService;
import com.naiterui.ehp.bs.patient.dao.IDoctorDao;
import com.naiterui.ehp.bs.patient.prodocl.QaRecordDetail;
import com.naiterui.ehp.bs.patient.repository.IApDrFollowUpRecordFormRepository;
import com.naiterui.ehp.bs.patient.service.IApQaService;
import com.naiterui.ehp.bs.patient.vo.QaRecordExportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ApQaServiceImpl implements IApQaService {

    @Autowired
    private IApDrFollowUpRecordFormRepository followUpRecordFormRepository;

    @Autowired
    private IDrFollowUpRecordService followUpRecordService;

    @Autowired
    private IDoctorDao doctorDao;

    @Override
    public QaPageBO qaRecord(List<FollowUpRecordFormBO> records) throws BusinessException {

        Long qaId = records.get(0).getFollowUpFormId();
        LinkedHashMap<String, String> headCommon = getCommonMap();
        List<QaRecordBO> qaRecordBOList = new ArrayList<>();
        AtomicInteger sn = new AtomicInteger(1);
        Set<Long> drIds = records.stream().map(d -> d.getDoctorId()).collect(Collectors.toSet());
        Map<Long, Doctor> doctorMap = doctorDao.getDoctorInfoByDrIds(drIds);
        for (FollowUpRecordFormBO qaRecord : records) {
            List<QaRecordDetail> qaList = getQaList(qaRecord);
            LinkedHashMap<String, String> head = qaList.stream()
                    .collect(Collectors.toMap(QaRecordDetail::getKey,
                            QaRecordDetail::getLabel, (u, v) -> v, LinkedHashMap::new));
            headCommon.putAll(head);
            QaRecordBO tempQaRecordBO = new QaRecordBO();
            commonRecordBO(tempQaRecordBO, sn.getAndIncrement(), qaRecord, doctorMap);
            qaList.stream().forEach(o -> {
                tempQaRecordBO.put(o.getKey(), QaRecordDetailBO.builder()
                        .key(o.getKey())
                        .label(o.getLabel())
                        .type(o.getType())
                        .value(o.getValue())
                        .build());
            });
            qaRecordBOList.add(tempQaRecordBO);
        }
        List<DrFollowUpRecordForm> list = this.followUpRecordFormRepository.findByFollowUpFormId(qaId);
        long notFilledNumber = list.stream().filter(rf -> rf.getFillingStatus() == 0).count();
        long filledNumber = list.stream().filter(rf -> rf.getFillingStatus() == 1).count();

        String completePercent = BigDecimal.valueOf(filledNumber * 100).divide(BigDecimal.valueOf(list.size()), 2, BigDecimal.ROUND_HALF_DOWN).toString() + "%";

        return QaPageBO.builder()
                .title(list.get(0).getFormName())
                .head(headCommon)
                .view("")
                .statisTime(new Date())
                .completePercent(completePercent)
                .totalNumber((long) list.size())
                .notFilledNumber(notFilledNumber)
                .filledNumber(filledNumber)
                .exportUrl("")
                .pageNo(1)
                .pageSize(1)
                .result(qaRecordBOList)
                .totalCount(records.size())
                .build();
    }

    private List<QaRecordDetail> getQaList(FollowUpRecordFormBO record) throws BusinessException {
        List<QaRecordDetail> qaList = new ArrayList<>();
        //问卷只支持处理单表单
        DesignFormBO designFormDataVO = followUpRecordService.getDesignFormDataBO(record.getFormId(), String.valueOf(record.getId()));
        Map<String, Object> formDataMap = new HashMap<>();
        if (designFormDataVO.getFormData() != null && CollUtil.isNotEmpty(designFormDataVO.getFormData().values())) {
            formDataMap = designFormDataVO.getFormData().values().stream().findFirst().orElse(Collections.emptyMap());
        }
        for (FormDrawingBO tempDraw : designFormDataVO.getFormDrawing()) {
            String inputName = tempDraw.getInputname();
            Object value = formDataMap.getOrDefault(inputName, "");
            List<String> valueList;
            if (value instanceof List) {
                valueList = (List<String>) value;
            } else {
                valueList = Collections.singletonList(value + "");
            }
            if (CollUtil.isNotEmpty(tempDraw.getOptions())) {
                Map<String, String> labelMap = tempDraw.getOptions().stream().collect(Collectors.toMap(FormDrawingOptionBO::getOptionValue, FormDrawingOptionBO::getOptionLabel));
                valueList = valueList.stream().map(opv -> labelMap.getOrDefault(opv, "")).collect(Collectors.toList());
            }
            qaList.add(QaRecordDetail
                    .builder()
                    .key(inputName)
                    .label(tempDraw.getText())
                    .type("eImage".equals(tempDraw.getFieldType()) ? 2 : 1)
                    .value(valueList)
                    .build());
        }
        return qaList;
    }

    private void commonRecordBO(QaRecordBO tempQaRecordBO, int andIncrement, FollowUpRecordFormBO qaRecord, Map<Long, Doctor> doctorMap) {
        tempQaRecordBO.put("id", QaRecordDetailBO.builder()
                .key("id")
                .label("id")
                .type(0)
                .value(Collections.singletonList(qaRecord.getId() + ""))
                .build());
        tempQaRecordBO.put("sn", QaRecordDetailBO.builder()
                .key("sn")
                .label("序号")
                .type(0)
                .value(Collections.singletonList(andIncrement + ""))
                .build());
        tempQaRecordBO.put("inquirerName", QaRecordDetailBO.builder()
                .key("inquirerName")
                .label("随访人信息")
                .type(0)
                .value(Collections.singletonList(qaRecord.getInquirerName()))
                .build());
        tempQaRecordBO.put("inquirerGender", QaRecordDetailBO.builder()
                .key("inquirerGender")
                .label("性别")
                .type(0)
                .value(Collections.singletonList(qaRecord.getInquirerGender()))
                .build());
        tempQaRecordBO.put("inquirerAge", QaRecordDetailBO.builder()
                .key("inquirerAge")
                .label("年龄")
                .type(0)
                .value(Collections.singletonList(qaRecord.getInquirerAge()))
                .build());
        tempQaRecordBO.put("doctor", QaRecordDetailBO.builder()
                .key("doctor")
                .label("随访医生")
                .type(0)
                .value(Collections.singletonList(null == doctorMap.get(qaRecord.getDoctorId()) ? "未知" : doctorMap.get(qaRecord.getDoctorId()).getName()))
                .build());
        tempQaRecordBO.put("submitTime", QaRecordDetailBO.builder()
                .key("submitTime")
                .label("提交时间")
                .type(0)
                .value(Collections.singletonList(null == qaRecord.getSubmitAt() ? "" : DateUtil.formatDate(qaRecord.getSubmitAt(), DateUtil.DATE_TIME_FORMAT)))
                .build());
        tempQaRecordBO.put("status", QaRecordDetailBO.builder()
                .key("status")
                .label("表单状态")
                .type(0)
                .value(Collections.singletonList(qaRecord.getFillingStatus() == 0 ? "未填写" : "已填写"))
                .build());
    }

    private LinkedHashMap<String, String> getCommonMap() {
        LinkedHashMap<String, String> headCommon = new LinkedHashMap<>();
        headCommon.put("id", "id");
        headCommon.put("sn", "序号");
        headCommon.put("inquirerName", "随访人信息");
        headCommon.put("inquirerGender", "性别");
        headCommon.put("inquirerAge", "年龄");
        headCommon.put("doctor", "随访医生");
        headCommon.put("submitTime", "提交时间");
        headCommon.put("status", "表单状态");
        return headCommon;
    }

    @Override
    public byte[] qaRecordExport(List<FollowUpRecordFormBO> records) throws BusinessException {
        AtomicInteger sn = new AtomicInteger(1);
        Set<Long> drIds = records.stream().map(d -> d.getDoctorId()).collect(Collectors.toSet());
        Map<Long, Doctor> doctorMap = doctorDao.getDoctorInfoByDrIds(drIds);
        List<QaRecordExportVO> qaRecordExportList = new ArrayList<>();
        List<QaRecordDetail> qaList = new ArrayList<>();
        for (FollowUpRecordFormBO qaRecord : records) {
            List<QaRecordDetail> singleQaList = getQaList(qaRecord);
            QaRecordExportVO exportVO = new QaRecordExportVO();
            singleQaList.stream().forEach(o -> {
                exportVO.put(o.getKey(), o.getValue().stream().collect(Collectors.joining(",")));
            });
            exportVO.put("sn", sn.getAndIncrement() + "");
            exportVO.put("inquirerName", StringUtils.trimToEmpty(qaRecord.getInquirerName()));
            exportVO.put("inquirerGender", StringUtils.trimToEmpty(qaRecord.getInquirerGender()));
            exportVO.put("inquirerAge", StringUtils.trimToEmpty(qaRecord.getInquirerAge()));
            exportVO.put("doctor", null == doctorMap.get(qaRecord.getDoctorId()) ? "未知" : doctorMap.get(qaRecord.getDoctorId()).getName());
            exportVO.put("submitTime", null == qaRecord.getSubmitAt() ? "" : DateUtil.formatDate(qaRecord.getSubmitAt(), DateUtil.DATE_TIME_FORMAT));
            exportVO.put("status", qaRecord.getFillingStatus() == 0 ? "未填写" : "已填写");
            qaRecordExportList.add(exportVO);
            qaList = singleQaList;
        }
        Long qaId = records.get(0).getFollowUpFormId();
        List<ExcelExportEntity> entityList = qaList.stream().map(qaRecordDetail ->
                new ExcelExportEntity(qaRecordDetail.getLabel(), qaRecordDetail.getKey())).collect(Collectors.toList());
        entityList.add(0, new ExcelExportEntity("表单状态", "status"));
        entityList.add(0, new ExcelExportEntity("提交时间", "submitTime"));
        entityList.add(0, new ExcelExportEntity("随访医生", "doctor"));
        entityList.add(0, new ExcelExportEntity("年龄", "inquirerAge"));
        entityList.add(0, new ExcelExportEntity("性别", "inquirerGender"));
        entityList.add(0, new ExcelExportEntity("随访人信息", "inquirerName"));
        entityList.add(0, new ExcelExportEntity("序号", "sn"));
        return this.exportExcel(entityList, qaRecordExportList);
        /*String pathUrl = fullName.replaceAll("/" + ConfigUtil.getString("file.base.prefix"), ConfigUtil.getString("img.hosts"));
        //TODO 2020/3/13 7:11 下午 高亮亮 暂时通过PC\CMS token判断同一用户导出任务
        log.info("fullName={},pathUrl={}", fullName, pathUrl);
        RedisUtil.hashOps().hset(QaConstants.EXPORT_REDIS_KEY, token + qaId, pathUrl);*/
    }

    public byte[] exportExcel(List<ExcelExportEntity> entityList, Collection<?> list) throws BusinessException {
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entityList, list);
        ByteArrayOutputStream out = null;
        try {
            out = new ByteArrayOutputStream();
            workbook.write(out);
            out.close();
        } catch (Exception e) {
            throw new BusinessException(ExceptionCodes.FAILED, "excel 文件导出失败");
        }
        return out.toByteArray();
    }
}
